class Snake {
  // 表示蛇头的元素
  head: HTMLElement
  // 蛇身部分 (包括头)
  bodies: HTMLCollection
  // 获取蛇的容器
  element: HTMLElement

  constructor() {
    this.element = document.getElementById('snake')!
    this.head = document.querySelector('#snake > div') as HTMLElement
    this.bodies = this.element!.getElementsByTagName('div')
    
  }

  // 获取蛇的坐标(蛇头坐标)
  get X() {
    return this.head.offsetLeft
  }
  // 获取蛇头的Y轴坐标
  get Y() {
    return this.head.offsetTop
  }

  // 设置蛇头的坐标
  set X(value:number) {
    // 如果新值和旧值相同,则直接返回不再修改
    if(this.X === value){
      return
    }

    if(value < 0 ||value>290) {
      // 进入判断说明蛇撞墙了,抛出一个异常
      throw new Error('蛇撞墙了');
    }
    
    // 修改x时, 是在修改水平坐标,蛇向左时不能向右
    if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
      // console.log('水平方向发生了掉头');
      // 如果发生了掉头, 让蛇向反方向继续移动
      if(this.X > value) {
        // 如果新值value小于旧值X,则说明蛇想向左,让他继续往右
        value = this.X + 10
      }else {
        value = this.X - 10
      }
    }
      
    // 移动身体
    this.moveBody() 
    this.head.style.left = value + 'px'
    // 检查有没有撞到自己
    this.checkHeadBody()
  }
  set Y(value:number) {
    // 如果新值和旧值相同,则直接返回不再修改
   
    if(this.Y === value){
      return
    }
    if(value < 0 ||value>290) {
      throw new Error('哎鸭,蛇撞墙了');
      
    }

    if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
      // 旧值大于新值,说明是往下走的,让蛇继续往下
      if(this.Y > value) {
        value = this.Y + 10
      }else {
        value = this.Y - 10
      }
    }

    // 移动身体
    this.moveBody()

    this.head.style.top = value + 'px'
    // 检查有没有撞到自己
    this.checkHeadBody()
  }

  // 蛇增加身体的方法
  addBody() {
    // 向element中添加一个div
    this.element.insertAdjacentHTML("beforeend","<div></div>")
  }

  // 添加一个蛇身体移动的方法
  moveBody() {
    /* 
      将后边的身体设置为前边身体的位置
    */
    // 先遍历获取所有的身体
    for(let i = this.bodies.length-1; i > 0; i--){
      let left = (this.bodies[i-1] as HTMLElement).offsetLeft;
      let top = (this.bodies[i-1] as HTMLElement).offsetTop;
      
      // 将值设置到当前身体上去
      (this.bodies[i] as HTMLElement).style.left = left + 'px';
      (this.bodies[i] as HTMLElement).style.top = top + 'px';
    }
    

  }
    // 检查蛇头是否撞到身体的方法
    checkHeadBody() {
      //获取所有身体部分,检查其坐标是否和蛇头重叠
      for(let i = 1; i < this.bodies.length; i++) {
          let bd = this.bodies[i] as HTMLElement
        if(this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
          //蛇头撞蛇身
          throw new Error('哎鸭,撞到自己啦~')
        }
      }
    }

}
export default Snake